C/C++ Basic API

按照VoIP & IM Mobile SDK API的封装原则,C/C++ Basic API接口可划分为:基本功能接口、通话功能接口和对讲功能接口等三个功能模块。
下面分别说明各接口功能模块的具体使用方法。

基本功能接口

基本功能接口的函数原型参见“freepp_sdk.h”文件,主要提供应用管理、即时消息和群组管理功能。

应用/账号管理

初始化SDK库

函数原型 Bool Initialize(char* appKey, void* sdkDelegate);
参数 appKey:字符串,用于标识第三方APP的授权码。
sdkDelegate:任意指针类型,APP代理者对象的指针。(APP代理者对象主要负责实现SDK的回调函数,对象原型参见FreePPSDKDelegate)
返回值 布尔型,客户端初始化结果。成功返回true,失败返回false。
说明 初始化和启动SDK客户端模块。
注:APP授权码和云端服务入口地址需预先申请,初始化SDK前需预先通过SetParameter接口设置用户数据库路径和云端服务入口地址。
示例 char dbPath[1024] = “数据库文件的存放路径”;// 设置SDK数据库路径
int res = FreePPSDK::SetParameter(FREEPP_SDK_DB_PATH, dbPath);
if (res == 0)
{
// 设置云端服务的入口地址
char rootcs[256] = “云端服务的入口地址”;
FreePPSDK::SetParameter(FREEPP_ROOTCS_ADDRESS, rootcs);
// 初始化SDK
char appKey[256] =”APP的授权码”;
m_sdkDelegate = newAppDelegate;
m_bInitFreePPSDK = FreePPSDK::Initialize(appKey, m_sdkDelegate);
if (!m_bInitFreePPSDK)
{
AfxMessageBox(_T("SDK初始化失败失败!!!"));
}
}
else
{
AfxMessageBox(_T("SDK数据库路径设置失败!!!"));
}

绑定APP用户账号

函数原型 int BindAppAccount(char*appUserAccount,bool mustAuth,char *outFreePPID);
参数 appUserAccount:字符串,App帐号(长度不超过40字节)。 mustAuth:布尔值,此参数为true时,SDK强制到服务器进行远程身份验证,否则SDK将自动判断是否需要到服务器上进行认证,或者在本地数据库中完成认证。这样,APP可以自己决定是否要互踢或者快速登录。 outFreePPID:输出参数,字符串,用于接收与此账号绑定的freepp号码。如果绑定成功,该参数则赋值为该freepp号码。
返回值 整型,0=绑定APP账号和通信号码成功,其它值=错误代码
说明 首先验证App的合法性,然后分配和绑定通信号码,最后登录即时通信系统的云平台。 注:当第一次bind时,需要访问服务器,APP要确保网络是连接的。APP除必须采用强制认证方式(例如:强制到服务器验证身份)的情况之外,在其它情况下推荐使用自动验证方式(mustAuth=FALSE),以提高登录的速度。
示例 char freeppID[256] = { 0 }; char account[256] = “APP账号”; if (strlen(account) > 40) { AfxMessageBox(_T("用户名超过40字节,请重新输入!")); return -1; } if( FreePPSDK::BindAppAccount(account, false, freeppID)!= 0) { AfxMessageBox(_T("appKey验证失败或者绑定失败!")); return -1; }

登出当前绑定的APP账号

函数原型 int LogoutAppAccount()
参数
返回值 整型,0=成功,其它=错误代码。 -15: SDK未初始化或没有绑定成功。
说明 重置当前帐号,清除本地的账号记录和缓存的消息。
示例 int res = FreePPSDK::LogoutAppAccount(); if (res != 0) { AfxMessageBox(_T("Logout失败,res = %d!",res)); return; }

查询通信号码

函数原型 intQueryFreePPIDByAppAccount(const char* jsonAccountArray, char*outJsonAccountFreePPID);
参数 jsonAccountArray:JSON字符串,指定查询目标的APP账号。例如: ["abner1","abner2","abner3","abner4"]。 outJsonAccountFreePPID:输出参数,JSON字符串,用于接收SDK返回的通信号码信息。例如: {"abner1":"30905341","abner2":"30905127","abner3":"30905543","abner4":"30904794"}。 有关JSON字符串的解析可参考示例程序
返回值 整型,0=查询通信号码成功,其它值=错误代码;
说明 根据APP账号查询通信号码。
示例 vector arrayAccounts;// 用户APP账户列表 string strAccounts; WriteJson(arrayAccounts, strAccounts);// 写Json字符串 char strJsonAccountFreePPIds[1024] = { 0 }; if(FreePPSDK::QueryFreePPIDByAppAccount(strAccounts.c_str(), strJsonAccountFreePPIds)!=0) { AfxMessageBox(_T("获取FreePP号失败,请确认查询用户是否为FreePP用户!")); } else { // 解析JSON字符串 }

查询APP账号

函数原型 intQueryAppAccountByFreePPID(const char* jsonFreePPIDArray, char* outJsonFreePPIDAccount);
参数 jsonFreePPIDArray:JSON字符串,指定查询目标的APP账号,例如: ["30905341","30905127","30905543","30904794"]。 outJsonFreePPIDAccount:输出参数,JSON字符串,用于接收SDK返回的APP账号信息,例如:{"30905341":"abner1","30905127":"abner2","30905543":"abner3","30904794":"abner4"}。
返回值 整型,0=查询APP账号成功,其它值=错误代码;
说明 根据通信号码(FreePPID)查询APP账号。
示例 vector arrayFreePPIDs;// 用户FreePPID列表 string strFreePPIDs; WriteJson(arrayFreePPIDs, strFreePPIDs);// 写Json字符串 char strJsonFreePPIDAccounts[1024] = { 0 }; if(FreePPSDK::QueryFreePPIDByAppAccount(strFreePPIDs.c_str(), strJsonFreePPIDAccounts)!=0) { AfxMessageBox(_T("查询APP账号失败,请确认FreePPID是否正确!")); } else { // 解析JSON字符串 }

修改SDK参数配置

函数原型 intSetParameter(char *name, char *value);
参数 name:字符串,参数名称。 value:字符串,参数值。
返回值 整型,0-设置成功,错误码参考错误码表。
说明 设置SDK内部的配置参数。 注:目前支持的配置参数参见附录1。
示例 参见Initialize代码。

读取SDK参数配置

函数原型 voidGetParameter(char *name, char *outValue);
参数 name:输入参数,字符串,参数名称。 outValue:输出参数,字符串,用于接收返回的参数值。
返回值
说明 读取SDK内部的参数值。
示例 参见Initialize示例代码。

追踪错误代码

函数原型 int GetLastErrorCode();
参数
返回值 整型,错误代码。如果没有错误,则返回0.
说明 读取最后一次接口调用失败的错误码。 注:此接口为线程安全的,即保证不同线程最后一次错误是独立保存的,如果调用此接口后,SDK即会清除当前线程的错误码。
示例 int lastErrorCode = GetLastErrorCode(); switch (lastErrorCode) { caseSUCCESS_CODE: { AfxMessageBox(_T("无错误!")); } break; caseERROR_NETWORK_NO_CONNECTION: { AfxMessageBox(_T("没有网络链接!")); } break; caseERROR_FREEPP_API_TIMEOUT: { AfxMessageBox(_T("API请求超时或出错!")); } break; caseERROR_ROOTCS_INVALID: { AfxMessageBox(_T("rootcs没有设置!")); } break; caseERROR_PARAMETER: { AfxMessageBox(_T("参数不合法!")); } break; caseERROR_FREEPP_SDK_UNINITIALIZED: { AfxMessageBox(_T("FreePP SDK未初始化或绑定成功!")); } break; default: break; }

响应系统消息

函数原型 CALLBACK virtual voidonSystemEvent(int eventType, void* dataOjbect) = 0;
参数 eventType:输入参数,整型,事件类型,包含:1=当前用户被踢出;对应的 data 为 NULL。 dataOjbect:输入参数,根据事件类型对应不同的数据对象,也可以为 NULL。
返回值
说明 向APP推送与当前用户帐号有关的系统事件。
示例 voidFreePPSDKDelegate::onSystemEvent(inteventType, void* dataOjbect) { char log[256]; switch (eventType) { caseEVENT_TYPE_KICKOUT: // 1=当前用户被踢出 sprintf(log,"EVENT_TYPE_KICKOUT = 1"); //异步执行登出当前绑定的APP账号 FreePPSDK::LogoutAppAccount(); break; default: break; } }
即时消息

发送一对一消息

函数原型 int SendMessage (char* dstFreePPID, char* mimeType, char* textContent, char* filePath, char* messageID, char* outMessageID);
参数 dstFreePPID:字符串,目标用户的通信号码。 mimeType:字符串,多媒体消息的类型,例如:”text/plain” textContent:字符串,文本消息的内容,其格式根mimeType来区分。如果为text/plain则为纯文本字符串。 filePath:字符串,消息文件的本地文件路径。 messageID:字符串,如果是重试发送消息的消息ID。 outMessageID:输出参数,字符串,用于接收消息ID的字符串缓冲区。消息ID格式为“本地通信号码-Unix时间戳(秒)-两位序号”。如果发送消息失败,则此字符串为空。
返回值 整型,消息处理结果。0=消息已被排入发送队列,等待发送;其它值=错误代码。
说明 向指定的用户异步地发送一对一的多媒体消息。 注:此接口为异步接口,可触发回调函数包括onSendMessageEvent和onUploadAttacthmentProgressEvent。 如果messageID参数有值,则SDK会判断此消息ID是否有效。对于有效的消息,SDK将重新发送此消息ID对应的消息内容;对于无效的消息,SDK则直接返回错误代码。
示例 // m_textContent需发送的文本,文本长度不大于1024字节 if (m_textContent.GetLength() >1024) { AfxMessageBox(_T("文本内容太长,请分条发送!")); return; } char dstFreePP[256] = { 0 }; char mimeType[32] = { 0 }; char textContent[FREEPP_MMS_TEXT_MAX_LENGTH] = { 0 }; char retryMsgId[256] = { 0 }; char filePath[512] = { 0 }; CopyString(m_dstFreePPUser, dstFreePP, 256); vector dstFreePPId; GetFreePPIdsByAccounts(dstFreePP, dstFreePPId);//获取目标用户的通信号码 if (dstFreePPId.size() == 0) { AfxMessageBox(_T("查询通信号码失败!")); return; } // 将Unicode字符转换为multibyte CopyString(m_filePath, filePath, 512); CopyString(m_msgType, mimeType, 32); char msgID[256] = { 0 }; if(FreePPSDK::SendMessage ((char*)dstFreePPId.at(0).c_str(), mimeType, textContent, filePath, retryMsgId, msgID)!=0) { AfxMessageBox(_T("发送消息失败!")); return; }

发送群组消息

函数原型 int SendGroupMessage (char *dstGroupID, char *mimeType, char *textContent, char *filePath, char *messageID, char *outGroupMesaageID);
参数 dstGroupID:字符串,目标群组的唯一标识符。 mimeType:字符串,多媒体消息的类型。 textContent:字符串,文本消息的内容,其格式根据mimeType来区分。 filePath:字符串,消息文件的本地文件路径。 messageID:字符串,如果是重试发送消息的消息ID。 outMessageID:输出参数,字符串,用于接收消息ID的缓冲区。消息ID格式为:“通信号码-Unix时间戳(秒)-两位序号”。如果发送失败,则返回NULL。
返回值 整型,消息处理结果。0=消息已被排入发送队列,等待发送;其它值=错误代码。
说明 向指定的群组异步地发送一对多的多媒体消息。 注:此接口为异步接口,可触发回调函数OnSendMessageEvent和onUploadAttacthmentProgressEvent。 如果messageID参数有值,则SDK会判断此消息ID是否有效。对于有效的消息,SDK将重新发送此消息ID对应的消息内容;对于无效的消息,SDK则直接返回错误代码。 注:群组的标识符ID可通过调用CreateGroupChat接口,或者接收到群组消息时从通知中获得。
示例 if (m_dstGroupID.GetLength() == 0) { AfxMessageBox(_T("目标群ID为空!")); return; } // Unicode to Multibyte coding char mimeType[32] = { 0 }; CopyString(m_msgType, mimeType, sizeof(mimeType)); char retryMsgId[256] = { 0 }; char filePath[256] = { 0 }; CopyString(m_filePath, filePath, sizeof(filePath)); char groupMsgID[256] = { 0 }; char groupID[64] = { 0 }; CopyString(m_dstGroupID, groupID, 64); char groupMsgData[FREEPP_MMS_TEXT_MAX_LENGTH] = { 0 }; if (m_textContent.GetLength()

清除缓存的消息

函数原型 void ClearMessage(char* messageIDArray);
参数 messageIDArray:JSON字符串,被释放的消息的标识符列表。例如:[”call-id1”,”call-id2”]。
返回值
说明 清除SDK内部存储的消息记录。 注:APP在接收或发送消息成功后,可调用此函数以清除SDK中的缓存记录。
示例 vector msgIds; string dstMsgIds; WriteJson(msgIds, dstMsgIds); //写Json字符串 FreePPSDK::ClearMessage( (char*)dstMsgIds.c_str());

检查新消息

函数原型 void CheckNewMessage();
参数
返回值
说明 客户端主动到服务器上检查和下载新消息。 注:此接口为异步接口,可触发回调函数onReceiveMessageEvent。
示例 FreePPSDK::CheckNewMessage( );

响应消息发送结果

函数原型 virtual void onSendMessageEvent(char* messageID, int sendResult) = 0;
参数 messageID:字符串,发送消息的唯一标识ID。 sendResult:整型,发送消息的结果。0=成功,发送失败参照错误码表。
返回值
说明 APP通过此接口获得一对一或群聊消息消息的发送状态。 注:对于发送文本消息和文件消息,均使用此回调函数来获得消息发送结果;对于文件型消息,还可以通过onUploadMessageAttachmentProgressEvent回调函数获取文件传输的进度。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此回调函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 voidFreePPSDKDelegate::onSendMessageEvent(char* messageID, intsendResult) { CWinPhoneDlg *dlg = (CWinPhoneDlg *)theApp.m_pMainWnd; char msgID[256] = { 0 }; char groupMsgID[256]; CopyString(dlg->mmsTestDlg->m_sendMsgID, msgID, 256); CopyString(dlg->mmsTestDlg->m_sendGroupMsgID, groupMsgID, 256); if (strcmp(msgID, messageID) == 0) { //异步处理一对一消息结果 } elseif (strcmp(groupMsgID,messageID) == 0) { //异步处理群组消息结果 } }

获取到新消息

函数原型 virtual voidonReceiveMessageEvent(int msgType, void *msgObject) = 0;
参数 msgType:整型,消息类型,取值为 0 = 一对一消息/群组消息类型; 1 = 加入群组通知类型; 2 = 离开群组类型; 3 = 消息接收状态通知类型 msgObject:消息对象,每种消息类型分别对应不同的对象,具体定义参考附录3“消息对象对照表”
返回值
说明 App通过此回调函数接收一对一或群组消息。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此回调函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 voidFreePPSDKDelegate::onReceiveMessageEvent(intmsgType, void * msgObject) { ... switch (msgType) { CaseMESSAGE_BOJECT_TYPE_MMS: // 一对一消息/群组消息 { Message * messageOjbect = (Message *)msgObject; // 异步处理接收的消息 … // 如果是单聊则报告消息的状态 if (messageOjbect->sessionType == SESSION_SINGLE_CHAT) { // 向发送端报告:已送达 FreePPSDK::ReportMessageStatus(messageOjbect->srcFreePPID,messageOjbect->messageID,MESSAGE_STATUS_RECEIVED); //向发送端报告:已读 FreePPSDK::ReportMessageStatus (messageOjbect->srcFreePPID, messageOjbect->messageID,MESSAGE_STATUS_READED); } } break; caseMESSAGE_BOJECT_TYPE_JOIN: // 加入群组通知 { JoinGroupMessage * joinGroupMessage = (JoinGroupMessage *)msgObject; // 异步处理接收的消息 // ...... } break; caseMESSAGE_BOJECT_TYPE_LEAVE: // 离开群组 { LeaveGroupMessage * leaveGroupMessage = (LeaveGroupMessage *)msgObject; // 异步处理接收的消息 // ...... } break; caseMESSAGE_BOJECT_TYPE_STATUS:// 消息送达状态通知 { MessageStatus * messageStatus = (MessageStatus *)msgObject; // 异步处理接收的消息 // ...... } break; default: break; } }

报告消息接收状态

函数原型 intReportMessageStatus(char *dstFreePPID, char *messageID, int status);
参数 dstFreePPID:字符串,目标用户的通信号码。 messageID:字符串,消息的唯一标识ID。 status:整型,发送消息接收状态通知的类型,包括:1 = 已送达,2 = 已读。
返回值 整型,报告处理结果。0=已加入发送队列发送,-1无网络无法发送。
说明 向指定用户发送一对一消息接收状态通知,包括消息送达和已读通知。
示例 详见onReceiveMessageEvent示例代码。

下载消息附件

函数原型 intDownloadMessageAttachment(char *messageID, int isThumbnail, char *filePath);
参数 messageID:字符串,要求下载的消息的唯一标识。 isThumbnail:整型,是否要下载缩略图,1-下载缩略图,0-下载原图,非图片类型无效参数。 filePath:字符串,下载到本地的文件路径,包含文件的名称。
返回值 整型,下载附件的处理结果。0=已加入到下载队列中,其他错误码参考错误码表。
说明 下载指定消息中的附件(多媒体文件)。 注:App首先通过OnReceivedMessageEvent接口获得消息通知,然后再调用downloadMessageAttachment接口下载消息中的附件。 注:此接口为异步接口,可触发回调函数onDownloadMessageAttachmentProgressEvent和onDownloadMessageAttachmentEvent,分别用于获取下载进度和下载结果。
示例 char messageID[256] = { 0 }; char filePath[512] = { 0 }; CopyString(m_recGroupMsgID, messageID, 256); CopyString(m_filePath, filePath, 512); if(FreePPSDK::DownloadMessageAttachment(messageID, 0, filePath)!=0) { printf(“下载消息附件失败”); }

响应消息下载结果

函数原型 virtual void onDownloadMessageAttachmentEvent(char *messageID, int downloadResult) = 0;
参数 messageID:字符串,被下载的消息的唯一标识符。 downloadResult:整型,下载消息的结果。0=成功,其它值为下载失败的错误代码(参见附录2)。
返回值
说明 APP通过此接口更新消息附件的下载状态。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此回调函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 voidFreePPSDKDelegate::onDownloadMessageAttachmentEvent(char *messageID, intdownloadResult) { CWinPhoneDlg *dlg = (CWinPhoneDlg *)theApp.m_pMainWnd; char msgID[256] = { 0 }; char groupMsgID[256]; CopyString(dlg->mmsTestDlg->m_sendMsgID, msgID, 256); CopyString(dlg->mmsTestDlg->m_sendGroupMsgID, groupMsgID, 256); if (strcmp(msgID, messageID) == 0) // 是否与当前发送的一对一消息匹配 { //异步处理消息结果 } elseif (strcmp(groupMsgID,messageID) == 0) // 是否与当前发送的群组消息匹配 { //异步处理消息结果 } }

响应消息附件的上传进度

函数原型 virtual void onUploadMessageAttachmentProgressEvent(char *messageID,int uploadProgress) = 0;
参数 messageID:字符串,被上传消息的唯一标识符; uploadProgress:整型,上传文件进度的百分比。
返回值
说明 APP可通过此回调函数更新文件上传的进度提示。 注:文件上传由sendMessage或sendGroupMessage接口发起。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此回调函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 voidFreePPSDKDelegate::onUploadMessageAttachmentProgressEvent(char *messageID, intuploadProgress) { //显示消息进度 }

响应消息附件下载进度

函数原型 virtual void onDownloadMessageAttachmentProgressEvent(char* messageID, int downloadProgress) = 0;
参数 messageID:字符串,消息的唯一标识符; downloadProgress:整型,当前下载文件进度的百分比
返回值
说明 APP可通过此回调函数更新文件下载的进度提示。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此回调函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 voidFreePPSDKDelegate::onDownloadloadMessageAttachmentProgressEvent(char *messageID, intdownloadProgress) { //CWinPhoneDlg *dlg = (CWinPhoneDlg *)theApp.m_pMainWnd; //char msgID[256]; //CopyString(dlg->mmsTestDlg->m_sendMsgID, msgID, 256); //char msgGroupID[256]; //CopyString(dlg->mmsTestDlg->m_sendGroupMsgID, msgGroupID, 256); //CString strUploadProgress = _T(""); //strUploadProgress.Format(_T("%d"), downloadProgress); //strUploadProgress.Append(_T("%")); //if (strcmp(msgID, messageID) == 0 || strcmp(msgGroupID, messageID) == 0) //{ //显示消息进度 //} }
群组管理

创建消息群组

函数原型 int CreateGroupChat(char *groupName, char *memberArray,char *outGroupID);
参数 groupName:字符串,创建群组的主题。 memberArray:字符串,群组成员的通信号码列表。 outGroupID:输出参数,字符串,用于接收创建群组的信息。如果创建成功,则返回新建群组的唯一标识符。
返回值 整型,创建群组的结果。0=创建成功,其它值为错误代码。
说明 创建一个新的消息群组,并指定群组中的用户。
示例 if (m_groupName.GetLength() == 0 || m_memberArray.GetLength() == 0) { AfxMessageBox(_T("群组名为空或群组成员为空!")); return; } char groupName[256] = { 0 }; char dstAccounts[1024] = { 0 }; // Unicode to Multibyte CopyString(m_groupName, groupName, 256); CopyString(m_memberArray, dstAccounts, 1024); vector freepps; GetFreePPIdsByAccounts(dstAccounts, freepps); //获取邀请用户的FreePP号 if (freepps.size() == 0) { AfxMessageBox(_T("邀请账号无效")); return; } string dstFreePPIds; WriteJson(freepps, dstFreePPIds); //写Json字符串 char groupID[64] = { 0 }; if(FreePPSDK::CreateGroupChat(groupName, (char*)dstFreePPIds.c_str(), groupID)!=0) { AfxMessageBox(_T("创建群组失败!")); return; }

邀请联系人加入消息群组

函数原型 intJoinGroupChat(char *groupID, char *memberArray);
参数 groupID:字符串,创建群组时返回的群组标识符。 memberArray:JSON字符串,被邀请的群组成员的通信号码列表,例如: ["abner1","abner2","abner3","abner4"]。
返回值 整型,加入群组的结果。0=成功,其它参见附录2
说明 邀请用户加入指定的消息群组,被邀请的客户端会以即时消息的形式收到邀请通知。
示例 if (m_groupID.GetLength() == 0 || m_memberArray.GetLength() == 0) { AfxMessageBox(_T("群ID为空或邀请成员为空!")); return; } char groupID[64] = { 0 }; char dstAccounts[1024] = { 0 }; CopyString(m_groupID, groupID, 64); CopyString(m_memberArray, dstAccounts, 1024); vector freepps; GetFreePPIdsByAccounts(dstAccounts, freepps);//查询通信号码(FreePP ID) if (freepps.size() == 0) { AfxMessageBox(_T("邀请账号无效")); return; } string dstFreePPIds; WriteJson(freepps, dstFreePPIds);//写Json字符串 // 邀请加入群组 if(FreePPSDK::JoinGroupChat(groupID, (char*)dstFreePPIds.c_str())!=0) { AfxMessageBox(_T("邀请用户加入群聊失败!")); return; }

退出消息群组

函数原型 int LeaveGroupChat(char *groupID);
参数 groupID:字符串,群组的唯一标识符。
返回值 整型,离开群组的结果。0=成功,其它参见附录2
说明 退出指定的消息群组。
示例 if (m_groupID.GetLength() == 0) { AfxMessageBox(_T("群ID为空!")); return; } char groupID[64] = { 0 }; CopyString(m_groupID, groupID, 64); int Res = FreePPSDK::LeaveGroupChat(groupID); if (Res != 0) { AfxMessageBox(_T("离开群组失败!")); return; } else { AfxMessageBox(_T("离开群组成功!")); }

获取指定群组信息

函数原型 boolGetGroupChatInfo(char *groupID, GroupInfo* groupInfo);
参数 groupID:字符串,群组的唯一标识符。 groupInfo:群组对象( GroupInfo ),用于保存获取的群组信息。包含以下属性: groupID:字符串,群组唯一标识; ownerFreePPID:字符串,群创建者的通信号码; arrayMemberFreePPID:字符串数组,群成员的通信号码; createTime: 整型,创建群组的时间; groupName:字符串,群名称或主题;
返回值
说明 获得指定群组的信息。
示例 if (m_groupID.GetLength() == 0) { AfxMessageBox(_T("群ID为空!")); return; } GroupInfo* getGroupInfo = (GroupInfo*)malloc(sizeof(GroupInfo)); memset(getGroupInfo, 0, sizeof(GroupInfo)); int m_num = sizeof(GroupInfo); char groupID[64] = { 0 }; CopyString(m_groupID, groupID, 64); FreePPSDK::GetGroupChatInfo(groupID, getGroupInfo); if (strlen(getGroupInfo->arrayMemberFreePPID) > 0) { CString messageString; messageString.Format(_T("GetGroupInfo: ID = %s, Name = %s, Owner = %s, Member = %s createTime = %d /n"), CStringW(getGroupInfo->groupID),CStringW(getGroupInfo->groupName),CStringW(getGroupInfo->ownerFreePPID), CStringW(getGroupInfo->arrayMemberFreePPID), getGroupInfo->createTime); m_mmsLogList.AddString(messageString); }

获取当前登录用户的所有群组信息(该接口目前只在阿里云服务器上部署)

函数原型 int GetGroupChatInfoList(char*groupsInfoBuf, int*groupsInfoBufLen);
参数 groupsInfoBuf:输出参数,JSON字符串,用于接收所有群组信息。例如: { "groups": [{"owner":"30902930", "mmsgroupid" : "30902930000004", "createtime" :"1435216718", "server" : "121.41.33.219", "groupname" :"GroupNameTest", "attendee" : ["30902930", "30904102", "30904646"]}, { "owner":"30902930", "mmsgroupid" : "30902930000002", "createtime" :"1435216717", "server" : "121.41.33.219", "groupname" : "GroupNameTest", "attendee" : ["30902930", "30904102", "30904646"] }, { "owner":"30902930", "mmsgroupid" : "30902930000003", "createtime" : "1435216717", "server" : "121.41.33.219", "groupname" : "GroupNameTest", "attendee" : ["30902930", "30904102", "30904646"] }]} groupsInfoBufLen:int型指针,传入接收BUF的长度。如果BUF长度不足以保存查询结果,返回保存结果所需的BUF长度。
返回值 整型,0=获取所有群组信息成功,-1=接收查询结果的BUF长度不够,其它值=错误代码。当返回-1时,groupsInfoBufLen返回接收结果所需的BUF长度。
说明 获得当前登录用户的所有群组信息。 注:若返回值为-1,表示用于接收结果的BUF长度不够,应用程序应该立即再调用一次,按照返回的长度信息,传入足够长度的BUF。
示例 char groupInfoList[2048] = { 0 }; int bufLen = sizeof(groupInfoList); int res = FreePPSDK::GetGroupChatInfoList(groupInfoList, &bufLen); if (-1 == res) { char* infoListBuf = (char*)malloc(bufLen); memset(infoListBuf, 0, bufLen); res = FreePPSDK::GetGroupChatInfoList(infoListBuf, &bufLen); if (0 == res) { CString groupInfo = _T(""); wchar_t* wGroupInfoList = (wchar_t*)malloc(bufLen*sizeof(wchar_t)); wmemset(wGroupInfoList, 0, bufLen); FreePPSDK::UTF8StringtoUnicodeCString(infoListBuf, wGroupInfoList, bufLen); groupInfo = wGroupInfoList; m_mmsLogList.AddString(groupInfo); free(wGroupInfoList); wGroupInfoList = NULL; } free(infoListBuf); infoListBuf = NULL; } elseif (0 == res) { CString groupInfo = _T(""); wchar_t* wGroupInfoList = (wchar_t*)malloc(bufLen*sizeof(wchar_t)); FreePPSDK::UTF8StringtoUnicodeCString(groupInfoList, wGroupInfoList, bufLen); groupInfo = wGroupInfoList; m_mmsLogList.AddString(groupInfo); }
辅助接口

UNICODE编码转UTF-8编码

函数原型 int UnicodeCStringtoUTF8String(wchar_t*uniString,char*outUTF8String,int outStrBufLen);
参数 uniString:待转码的Unicode字符串。 outUTF8String:输出参数,接收转换后的UTF-8字符串的缓冲区。 outStrBufLen:接收UTF-8字符串的缓冲区长度。
返回值 整型,转码后UTF-8字符串的长度。
说明 将UNICODE编码字符串转换为UTF-8编码字符串。
示例 char memberArray[256] = { 0 }; int memberArrayLen = FreePPSDK::UnicodeCStringtoUTF8String(m_MemberArray.GetBuffer(0), memberArray, 256);// m_MemberArray为Unicode编码

UTF-8编码转UNICODE编码

函数原型 int UTF8StringtoUnicodeCString(char*utf8String, wchar_t*outUniCString, int outStrBufLen);
参数 utf8String:待转码的UTF-8字符串。 outUniCString:输出参数,接收转码后的Unicode字符串的缓冲区。 outStrBufLen:接收Unicode字符串缓冲区长度。
返回值 整型,转码后UNICODE字符串长度。
说明 将UTF-8编码字符串转换为UNICODE编码字符串。。
示例 Message * messageOjbect = (Message *)msgObject; wchar_t unicodeWchar[1024] = { 0 }; if (strlen(messageOjbect->textContent) > 0) //做UTF-8转UNICODE { int textLen = FreePPSDK::UTF8StringtoUnicodeCString(messageOjbect->textContent, unicodeWchar, 1024); }

通话功能接口

通话功能接口的函数原型声明参见“FreePPSDKStream_C.h”文件,主要提供一对一语音或视频通话、语音会议、视频会议和媒体I/O设备(麦克风、扬声器和摄像头)控制等功能。

通话/会议控制

发起一对一的语音/视频通话呼叫

函数原型 int MakeCall(const char *dstID, int media, char *outCallID);
参数 dstID:字符串,被叫用户的通信号码。 media:整型,通话的媒体类型。取值为 1=语音通话; 2=视频通话; outCallID:输出参数,字符串,通话的会话标识符(call-id)。
返回值 整型,0=呼叫成功,其它=错误代码,参见附录2。
说明 发起一对一的、免费的语音或视频通话。 注:此接口为异步接口,可触发回调函数onCallStateEvent。APP可根据此函数的返回值(call-id),在回调函数中匹配相应的通话状态通知。 注:如果是发起视频呼叫,APP需要先调用SetVideoDisplay杉树设置视频的远端和本地显示窗口。
示例 char callID[256] = {0}; switch (m_comboMediaType.GetCurSel()) { case 0: // 语音呼叫 m_nCallMediaType = MEDIA_AUDIO_TYPE; ret = FreePPSDK::MakeCall(dstFreePPIds.at(0).c_str(), m_nCallMediaType, callID); break; case 1: // 视频呼叫 m_nCallMediaType = MEDIA_VIDEO_TYPE; FreePPSDK::SetVideoDisplay(GetDlgItem(IDC_STATIC_REMOTE_VIDEO)->GetSafeHwnd(), GetDlgItem(IDC_STATIC_LOCAL_VIDEO)->GetSafeHwnd()); ret = FreePPSDK::MakeCall(dstFreePPIds.at(0).c_str(), m_nCallMediaType, callID); break; } if(ret != 0) { AfxMessageBox(_T("呼叫失败")); }

发起节费电话呼叫

函数原型 int MakeOutboundCall(const char *phone, const char *via, char *outCallID);
参数 phone:字符串,被叫电话号码。 via:字符串,Outbound路由码。 outCallID:输出参数,字符串,通话的会话标识符(call-id)。
返回值 整型, 0=呼叫成功,其它=参见附录2.
说明 发起一对一的、节费的outbound语音通话呼叫。 注:此接口为异步接口,可触发回调函数onCallStateEvent。APP可根据此函数的返回值(call-id),在回调函数中匹配相应的通话状态通知。 注:节费电话的收费标准,由Outbound Call的PSTN服务供应商提供,并可通过路由码区分不同的提供商。
示例 m_nCallMediaType = MEDIA_AUDIO_TYPE; char dstOutbound[256] = {0}; char via[256] = {0}; UpdateData(true); CopyString(m_szCallee, dstOutbound, 256); CopyString(m_szRSHost2, via, 256); ret = FreePPSDK::MakeOutboundCall(dstOutbound, via, callID); if(ret < 0) { AfxMessageBox(_T("呼叫失败")); }

结束通话

函数原型 int HangupCall (char *callID);
参数 callID:字符串,通话的会话标识符,一般由makeCall、makeOutboundCall、JoinConference或onReceiveCallEvent函数返回。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 结束一个通话(包括一对一或会议通话)或拒绝呼叫请求。 一对一通话:结束指定的一对一通话(主叫和被叫均可调用此函数)。此接口为异步接口,可触发回调函数onCallStateEvent。APP可根据此函数的返回值(call-id),在回调函数中匹配相应的通话状态通知。 对于客户端混音的会议通话:如果主持人调用此接口,且输入参数是会议标识符,则返回失败(主持人需调用HangupConference结束会议);如果与会者调用此接口,则挂断与主持人的通话,并触发回调函数onConferenceStateEvent。 对于服务器混音的会议通话:主持人和与会者均可调用此接口,结束自己的会议通话,并触发回调函数onConferenceStateEvent。
示例 if (m_szCallID.GetLength() != 0) { char callID[256]={0}; CopyString(m_szCallID, callID, 256); ret = FreePPSDK::HangupCall(callID); if (ret != 0) { AfxMessageBox(_T("挂断电话失败!!!")); return; } }

接听通话请求

函数原型 int AnswerCall (char *callID);
参数 callID:字符串,通话的会话标识符或者会议室标识符,一般由onReceiveCallEvent回调函数返回。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 被叫用户接听指定的来电请求。 注:在呼叫建立时,被叫用户会收到onReceiveCallEvent通知,且APP可从通知中获得来电请求的callID。此callID即可以是一对一通话标识符,也可以是会议的会话标识符。如果用户接受来电请求,则APP需要调用此函数接听来电;如果用户拒绝来电请求,则APP需调用hangupCall函数拒绝接听。 接听电话后,APP将收到回调函数onCallStateEvent或onConferenceStateEvent。APP可根据通话标识符,在回调函数中匹配相应的此通话的状态通知。
示例 int ret = -1; FreePPSDK::SetVideoDisplay(GetDlgItem(IDC_STATIC_REMOTE_VIDEO)->GetSafeHwnd(), GetDlgItem(IDC_STATIC_LOCAL_VIDEO)->GetSafeHwnd()); // 判断是否为一对一通话的标识符 if (m_szCallID.GetLength() != 0) { char callID[256]; CopyString(m_szCallID, callID, 256); ret = FreePPSDK::AnswerCall(callID); } // 判断是否为会议通话的标识符 else if (m_szConfID.GetLength() != 0) { char confID[256]; CopyString(m_szConfID, confID, 256); ret = FreePPSDK::AnswerCall(confID); } if (ret < 0) { AfxMessageBox(_T("接听失败")); return; }

通话保持或恢复

函数原型 int HoldCall (char *callID,int hold);
参数 callID:字符串,通话的会话标识符。 hold:整型,保持(1)或恢复(0)通话。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 保持或恢复指定的通话。 注:执行此操作后,APP将收到回调函数onCallStateEvent,并从通知中得到已进入保持或恢复状态。APP可根据通话标识符,在回调函数中匹配相应的此通话的状态通知。
示例 //hold按钮操作 int ret = -1; if (m_szCallID.GetLength() != 0) { char callID[256] = {0}; CopyString(m_szCallID, callID, 256); m_bHold = !m_bHold; ret = FreePPSDK::HoldCall(callID, m_bHold); if (ret == 0) GetDlgItem(IDC_BUTTON_HOLD)->SetWindowText(m_bHold ? _T("Resume") : _T("Hold")); } //onCallStateEvent()中实现 caseCALL_STATE_ANSWER: ... dlg->GetDlgItem(IDC_BUTTON_HOLD)->EnableWindow(true); dlg->m_bHold = false; break; caseCALL_STATE_HOLD: dlg->m_bHold = true; break;

通话静音或取消静音

函数原型 int MuteCall (char *callID,int mute);
参数 callID:字符串,通话的会话标识符或者会议室标识符 mute:整型,麦克风静音(1)或取消静音(0)。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 麦克风(或会议室主持人)静音或取消静音。 注:目前只实现一对一通话的静音功能。
示例 int ret = -1; staticint bMute = 1; if (m_szCallID.GetLength() != 0) { char callID[256]; CopyString(m_szCallID, callID, 256); bMute = !bMute; ret = FreePPSDK::MuteCall(callID, bMute); if (ret != 0) { AfxMessageBox(_T("静音失败")); return; } GetDlgItem(IDC_BUTTON_MUTE)->SetWindowText(bMute ? _T("Unmute") : _T("Mute")); }

发起通话录音

函数原型 int StartMediaRecord (char *callID,const char* Utf8FilePath, int media, int format=0, int intervalSec=0);
参数 callID:字符串,通话的会话标识符或者会议室标识符 Utf8FilePath:字符串,录音文件路径; meida:媒体类型,=1,audio;=2 video(暂不支持); format:整型,文件格式类型,0:mp3(默认),1:avi(暂不支持); intervalSec:整型,自动分段时间间隔,以秒为单位;默认为0,不分段。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 开始通话录音。 注:目前只实现一对一通话的录音功能。
示例

停止通话录音

函数原型 int StopMediaRecord (char *callID);
参数 callID:字符串,通话的会话标识符或者会议室标识符
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 停止通话录音。通过onRecordCallEvent()上报停止状态给app 注:目前只实现一对一通话的录音功能。
示例

发送DTMF拨号音

函数原型 int SendDTMF (char *callID,char *digit, int time, int mode);
参数 callID:字符串,通话的会话标识符。 digit:字符串,所要发送的二次拨号数字。 time:整形,发送多个按键数字时的时间间隔,单位:ms(注:若只发送一个数字,则此参数可为0)。 mode:整形,DTMF信号传输模式。
返回值 整型,操作是否成功。0=成功,其它=参见附录2。
说明 发送DTMF拨号音,完成二次拨号。
示例

发起语音或视频会议

函数原型 int JoinConference(const char *dstFreePPIDs, int media, const char *serverConferenceID,const char *dstPhones, char *via, char *outConferenceID);
参数 dstFreePPIDs:JSON字符串,与会者的通信号码,可以邀请多个与会者。 media:整型,会议的媒体类型。3=语音会议,4=视频会议 serverConferenceID:字符串,会议室的通信号码。如果会议室号码为用户本身的通信号码,则采用客户端混音方式;否则采用服务器混音方式。 dstPhones:JSON字符串,与会者的电话号码。 via:字符串,Outbound路由码。 outConferenceID:输出参数,字符串,会议的会话标识符(conference-id)。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 创建一个语音/视频会议。 注:此接口为异步接口,可触发回调函数onConferenceStateEvent,并从通知中得到自己是否已进入会议室。APP可根据此函数的返回值(conference-id),在回调函数中匹配相应的会议状态通知。 注:只有当通话类型是语音会议(=3)或者视频会议(=4)时,serverConferenceID参数才有效。 注:对于采用服务器混音的会议,APP需预先申请会议室号码。此外,针对同一个会议室,此函数可以被多次调用,以邀请不同的与会者加入同一个会议。
示例 char dstAccounts[256]; //被邀请者的appCount char svrConfID[256] = {0}; //会议室号码 int ret = -1; //保存被叫的freeppID到dstFreePPs CopyString(m_szCallee, dstAccounts, 256);// szCallee格式:123,456,3000 //保存会议室号码 CopyString(m_szSvrConfID, svrConfID, 256); char confID[256]; vector freepps; // 得到被邀请者的通信号码 GetFreePPIdsByAccounts(dstAccounts, freepps); if (freepps.size() == 0) { AfxMessageBox(_T("呼叫账号无效")); return; } string dstFreePPIds; WriteJson(freepps, dstFreePPIds);// dstFreePPIds为Json字符串 if (m_szConfID.GetLength() != 0) { //会议室中的与会者邀请其他人进入同一会议室 ret = FreePPSDK::JoinConference(dstFreePPIds.c_str(), m_nCallMediaType, svrConfID, NULL, NULL, confID); } else { // 新建会议 switch (m_comboMediaType.GetCurSel()) { case 3: // 语音会议 m_nCallMediaType = MEDIA_AUDIO_CONFERENCE_TYPE; ret = FreePPSDK::JoinConference(dstFreePPIds.c_str(), MEDIA_AUDIO_CONFERENCE_TYPE, svrConfID, NULL, NULL, confID); break; case 4: // 视频会议 m_nCallMediaType = MEDIA_VIDEO_CONFERENCE_TYPE; FreePPSDK::SetVideoDisplay(GetDlgItem(IDC_STATIC_REMOTE_VIDEO)->GetSafeHwnd(), GetDlgItem(IDC_STATIC_LOCAL_VIDEO)->GetSafeHwnd()); ret = FreePPSDK::JoinConference(dstFreePPIds.c_str(), MEDIA_VIDEO_CONFERENCE_TYPE, svrConfID, NULL, NULL, confID); break; default: AfxMessageBox(_T("MediaType 错误")); break; } } if(ret!=0) { // 邀请加入会议失败 } …. }

结束或退出会议

函数原型 int HangupConference(char *conferenceID);
参数 conferenceID:字符串,会议的标识符,一般由JoinConference或onReceiveCallEvent函数返回。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 APP可通过此接口结束指定的会议,并挂断会议中的所有与会者。 注:执行此操作后,APP将收到回调函数onConferenceStateEvent通知,并从通知中得到会议的状态。APP可根据会议标识符,在回调函数中匹配相应的此通话的状态通知;当客户端混音时,主持人调用该接口可以挂断所有与会者,与会者调用该接口只能挂断自己的会话;当服务器混音时,所有人都能调用该接口挂断整个会议室。
示例 // m_szConfID :会话标识符 if (m_szConfID.GetLength() != 0) { if (m_szConfID.Compare(m_szSvrConfID) == 0 || m_szConfID.Compare(m_strHostFreePPID) == 0) { char confID[256]; CopyString(m_szConfID, confID, 256); if(FreePPSDK::HangupConference(confID)==0) { m_szConfID = _T(""); // 结束会议成功,清除会议记录 } } }

刷新与会者列表

函数原型 int ListConference(char *conferenceID);
参数 conferenceID:字符串,会议的会话标识符,一般由JoinConference函数或onReceiveCallEvent回调函数返回。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 APP通过此接口可获取会议中的与会者的状态。 注:执行此操作后,APP将收到回调函数onConferenceStateEvent通知,并从通知中得到当前的与会者状态。APP可根据会议标识符,在回调函数中匹配相应的此会议的状态通知。
示例 // m_szConfID :会话标识符 if (m_szConfID.GetLength() != 0) { char confID[256]; CopyString(m_szConfID, confID, 256); FreePPSDK::ListConference (confID); }

会议控制

函数原型 int CtrlConference(char * conferenceID, int action, char *FreePPID);
参数 conferenceID:字符串,会议的会话标识符。一般由JoinConference函数或onReceiveCallEvent回调函数返回。 action:整型,要执行的控制动作。 0=踢出; 1=静音; 2=取消静音。 FreePPID:字符串,所控制的与会者的通信号码。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 APP可通过此接口对会议的与会者执行指定的会议控制动作。 目前只实现了踢人功能 注:此接口为异步接口,将触发回调函数onConferenceStateEvent。 APP可根据会议标识符,在回调函数中匹配相应的此通话的状态通知。
示例 // m_szConfID :会话标识符 // m_szConfCtrlFreeppID:将要被控制与会者的app账号 char confID[256]; char ctrlFreePPID[256]; CopyString(m_szConfID, confID, 256); CopyString(m_szConfCtrlFreeppID,ctrlFreePPID,256); vector freepps; GetFreePPIdsByAccounts(ctrlFreePPID, freepps);//从appCount中得到相应的通信号码 if (freepps.size() == 0) AfxMessageBox(_T("操作账号无效")); for (int i = 0; i < freepps.size(); i++) FreePPSDK::CtrlConference(confID, action, (char *)freepps.at(i).c_str());

选择视频会议画面

函数原型 int SubConferenceVideo(char* pubID);
参数 pubID:字符串,所要观看的与会者的通信号码。当pubID为NULL时,表示取消订阅,即不显示任何与会者的视频画面。
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 APP可通过此接口,为视频会议中的参与者(包括主持人和与会者)选择所观看的视频画面。 注:SDK采用出版/订阅模型实现视频画面选择,每个与会者可以订阅自己想观看的视频画面。
示例 // m_szConfCtrlFreeppID:将要被控制与会者的APP账号 char ctrlFreePPID[1024]; CopyString(m_szConfCtrlFreeppID, ctrlFreePPID, 256); vector freepps; GetFreePPIdsByAccounts(ctrlFreePPID, freepps);// 查询APP账号对应的通信号码 if (freepps.size() == 0) AfxMessageBox(_T("操作账号无效")); FreePPSDK::SubConferenceVideo((char *)freepps.at(0).c_str()); //一次订阅一个人
状态通知和查询

响应来电通知请求

函数原型 Virtual void onReceiveCallEvent(char *callId, char *callerId, char *callerName, int media, int callType) = 0;
参数 callId:字符串,通话的会话或者会议室标识符。 callerId:字符串,主叫用户的通信号码。 callerName:字符串,主叫用户的昵称或电话号码。 media:整型,通话请求的媒体类型,取值为1=语音通话;2=视频通话;3=语音会议通话;4=视频会议通话。 callType:整型,来电通知的类型,取值为1=新来电,2=未接来电。
返回值
说明 APP通过此接口接收其它用户的来电请求。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 //接口实现示例代码 void FreePPSDKDelegate::onReceiveCallEvent(char *callId, char *callerId, char *callerName, int media, int callType) { CWinPhoneDlg *dlg = (CWinPhoneDlg *)theApp.m_pMainWnd; CString callID(callId); dlg->GetDlgItem(IDC_STATIC_PEER)->SetWindowText(callID); //记录来电类型 dlg->m_nCallMediaType = media; //根据来电媒体类型做界面处理并记录标识符 switch (dlg->m_nCallMediaType) { // 语音或视频会议 caseMEDIA_AUDIO_CONFERENCE_TYPE: caseMEDIA_VIDEO_CONFERENCE_TYPE: dlg->GetDlgItem(IDC_BUTTON_SUB_VIDEO)->EnableWindow(true); dlg->GetDlgItem(IDC_BUTTON_KICK_ONE)->EnableWindow(true); dlg->m_szConfID = callID; dlg->m_szSvrConfID = callID; break; // 一对一语音或视频通信 caseMEDIA_AUDIO_TYPE: caseMEDIA_VIDEO_TYPE: dlg->m_szCallID = callID; dlg->m_szSvrConfID = callID; break; default: break; } //根据来电会话类型做界面处理 switch (callType) { caseRECEIVE_CALL_TYPE_INCOMING:// 来电通知 { dlg->GetDlgItem(IDC_STATIC_INCOMING)->SetWindowText(_T("Calling You...")); dlg->GetDlgItem(IDC_BUTTON_ANSWER)->EnableWindow(true); dlg->GetDlgItem(IDC_BUTTON_REJECT)->EnableWindow(true); } break; caseRECEIVE_CALL_TYPE_MISSED_CALL:// 未接电话通知 { dlg->GetDlgItem(IDC_STATIC_INCOMING)->SetWindowText(_T("Missed Call You")); dlg->GetDlgItem(IDC_BUTTON_ANSWER)->EnableWindow(false); dlg->GetDlgItem(IDC_BUTTON_REJECT)->EnableWindow(false); } break; default: break; } char log[256] = {0}; sprintf(log,"onReceiveCallEvent:callID=%s,callerID=%s,callerName=%s,meida=%d,callType=%d\n", callId, callerId, callerName, media, callType); dlg->PostMessage(WM_EVENT_LOG, NULL, (LPARAM)AllocStringBuffer(log));

响应通话状态改变通知

函数原型 virtual void onCallStateEvent(char*callId,intstate,intreason) = 0;
参数 callId:字符串,一对一通话的会话标识符。 state:整型,当前的通话状态,取值为 0 – IDLE(待机); 1 – INITIATE(正在发起呼叫); 2 – ANSWER(已接听); 3 – HOLD(保持中); 4 – HANGUP(已挂断)。 有关通话状态的说明可参考3.2.2节。 reason:整型。当state为HANGUP时标识结束通话的原因,包括:被叫不在线、没有可用的网络连接、被叫忙等,参考附录4;当state为ANSWER时表示进入通话的途径,包括:0 - 接听电话;1 - 恢复通话。
返回值
说明 APP通过此接口获知通话的状态发生改变的通知。在不同的通话状态下,APP应显示不同提示,例如:1) IDLE-无;2) NITIATE-正在呼叫中(主叫)或通话建立中(被叫);3) ANSWER-通话中;4) HOLD-通话保持中;5) HANGUP-通话结束。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 //接口实现示例代码 CWinPhoneDlg *dlg = (CWinPhoneDlg *)theApp.m_pMainWnd; char callID[256] = {0}; CString szHistory; CopyString(dlg->m_szCallID, callID, 256); if (strcmp(callID, callId) == 0) { switch (state) { caseCALL_STATE_IDLE: szHistory.Format(_T("空闲:")); dlg->GetDlgItem(IDC_STATIC_OUTGOING)->SetWindowText(szHistory); break; caseCALL_STATE_INITIATE: // 正在发起呼叫 if (dlg->m_isOutGoingCall) { szHistory.Format(_T("呼出电话:")); dlg->GetDlgItem(IDC_STATIC_OUTGOING)->SetWindowText(szHistory); } Else { szHistory.Format(_T("呼入电话:")); dlg->GetDlgItem(IDC_STATIC_INCOMING)->SetWindowText(szHistory); } dlg->GetDlgItem(IDC_BUTTON_HANGUP)->EnableWindow(true); break; caseCALL_STATE_ANSWER: szHistory.Format(_T("正在通话:")); dlg->GetDlgItem(IDC_STATIC_OUTGOING)->SetWindowText(szHistory); dlg->GetDlgItem(IDC_BUTTON_DIAL)->EnableWindow(false); dlg->GetDlgItem(IDC_BUTTON_HANGUP)->EnableWindow(true); dlg->GetDlgItem(IDC_BUTTON_ANSWER)->EnableWindow(false); break; caseCALL_STATE_HOLD: szHistory.Format(_T("通话保持中")); break; caseCALL_STATE_HANGUP: // 结束通话时,恢复待机画面 dlg->GetDlgItem(IDC_BUTTON_DIAL)->EnableWindow(true); dlg->GetDlgItem(IDC_BUTTON_HANGUP)->EnableWindow(false); dlg->GetDlgItem(IDC_BUTTON_ANSWER)->EnableWindow(false); dlg->GetDlgItem(IDC_BUTTON_REJECT)->EnableWindow(false); dlg->GetDlgItem(IDC_STATIC_INCOMING)->SetWindowText(_T("")); dlg->GetDlgItem(IDC_BUTTON_REJECT)->SetWindowText(_T("Reject")); dlg->m_szCallID = _T(""); dlg->GetDlgItem(IDC_BUTTON_HOLD)->EnableWindow(false); dlg->GetDlgItem(IDC_BUTTON_HOLD)->SetWindowText(_T("Hold")); dlg->GetDlgItem(IDC_BUTTON_MUTE)->EnableWindow(false); dlg->GetDlgItem(IDC_BUTTON_MUTE)->SetWindowText(_T("Mute")); szHistory = _T(""); dlg->GetDlgItem(IDC_STATIC_OUTGOING)->SetWindowText(szHistory); break; default: break; } char log[256] = {0}; sprintf(log, "onCallStateEvent:callID=%s,state=%d,reason=%d\n", callId, state,reason); dlg->PostMessage(WM_EVENT_LOG, NULL, (LPARAM)AllocStringBuffer(log));

响应会议中与会者状态改变通知

函数原型 virtual voidonConferenceStateEvent(char *conferenceId, char *callId, char *callerId, int state, int reason) = 0;
参数 conferenceId:字符串,会议的会话标识符,一般由JoinConference函数或onReceiveCallEvent回调函数返回(必须不为空)。 callId:字符串,与会者的通话标识符(可以为NULL)。 calleeId:字符串,与会者的通信号码。 state:整型,与会者当前的通话状态,取值为 1 – INITIATE(正在邀请); 2 – ANSWER(已进入); 3 – HANGUP(已离开)。 reason:整型。当state为HANGUP时,标识结束通话的原因,包括:被叫不在线、没有可用的网络连接、被叫忙等,参见附录4 - _call_hangup_reason;当state为ANSWER时表示进入通话的途径,包括:0 - 接听电话;1 - 恢复通话,参见附录4 - _call_answer_reason。
返回值
说明 APP通过此接口可获得会议中某个与会者的状态发生改变的通知。在不同的通话状态下,APP应显示不同的与会者状态提示:1) INITIATE-正在呼叫中(主叫)或通话建立中(被叫);2) ANSWER-进入会议;3) HANGUP-离开会议。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 //接口实现示例代码 virtual void FreePPSDKDelegate::onConferenceStateEvent(char *conferenceId, char *callId, char *callerId, int state, int reason) { if (conferenceId == NULL || callerId == NULL ||strlen(conferenceId) == 0 || strlen(callerId) == 0) { return; // 参数错误 } string strConventionerState; CWinPhoneDlg *dlg = (CWinPhoneDlg *)theApp.m_pMainWnd; CString callerID(callerId); switch (state) { caseCONFERENCE_STATE_INITIATE: // 正在邀请 strConventionerState = "1- INITIATE"; break; caseCONFERENCE_STATE_ANSWER: strConventionerState = "2-ANSWER"; // 已进入 break; caseCONFERENCE_STATE_HANGUP: // 已离开 strConventionerState = "3-LEAVE"; break; default: break; } char log[512] = {0}; sprintf(log, "onConferenceStateEvent:freeppid=%s,state=%s,reason=%d\n", callerId,strConventionerState.c_str(),reason); dlg->PostMessage(WM_EVENT_LOG, NULL, (LPARAM)AllocStringBuffer(log));

响应视频通信状态改变通知

函数原型 virtual void onRemoteVideoStateEvent(char *callId,int state) = 0;
参数 callId:字符串,通话或会议的会话标识符。 state:整型,当前的通话的远端视频状态,取值为0=停止;1=开启。
返回值
说明 APP通过此接口可获得视频通话中远端用户的视频发送状态的改变通知。在不同的视频状态下,APP可显示不同的界面。START:开启远端视频发送;STOP:停止远端视频发送。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 //接口实现示例代码 virtual voidonRemoteVideoStateEvent(char *callId,intstate) { CWinPhoneDlg *dlg = (CWinPhoneDlg *)theApp.m_pMainWnd; char callID[256] = {0}; string szState; CopyString(dlg->m_szCallID, callID, 256); if (strcmp(callID, callId) == 0) { switch (state) { caseREMOTE_VIDEO_START: // 正在发送视频 szState = "0- START"; break; caseREMOTE_VIDEO_STOP: // 停止发送视频 szState = "1- STOP"; break; default: break; } } char log[512] = {0}; sprintf(log, "onRemoteVideoStateEvent:callid=%s,state=%s\n", callId, szState.c_str()); dlg->PostMessage(WM_EVENT_LOG, NULL, (LPARAM)AllocStringBuffer(log)); }

响应通话录音状态改变通知

函数原型 virtual void onRecordStateEvent(char *filepath,int state) = 0;
参数 filepath:字符串,通话录音保存的文件名及路径。 state:整型,当前的通话录音状态,取值为1=开启;2=停止;3=转换成mp3完成。
返回值
说明 APP通过此接口可获得录音状态的改变通知。在不同的状态下,APP可显示不同的状态通知。1:开启录音;2:停止录音3:转换mp3完成。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例

查询通话的状态和信息

函数原型 bool GetCallInfo(char *callID, FreePPCallInfo* callInfo);
参数 callId:字符串,通话的会话标识符。 callInfo:输出参数,FreePPCallInfo指针类型,通话状态信息
返回值 布尔类型, true=获取成功,false=失败,原因是callID不存在;
说明 通过此接口,APP可获取指定通话的当前状态和详细信息,且将上述信息存放在FreePPCallInfo对象中返回。FreePPCallInfo对象包含如下属性: callId:字符串,通话或会议的会话标识符。 calleeId:字符串,对端用户的通信号码。 calleeName:字符串,对端用户的昵称或电话号码。 mediaType:整型,通话请求的媒体类型(语音、视频或会议)。 callState:整型,当前的通话状态,取值为:0 - IDLE;1 - INITIATE;2 - ANSWER;3 - HOLD;4 - HANGUP。
示例

获得当前正在进行的通话列表

函数原型 void GetAllCallIDList(char *outCallIDList);
参数 outCallIDList:输出参数,JSON字符串,包含所有通话的会话标识符。APP获取JSON字符串后需要进行json解析。
返回值
说明 获取当前所有呼出和呼入通话的call-id字符串的列表。 注:APP可首先调用此函数获得call-id列表,然后再调用getCallInfo函数获得通话的状态和详细信息。
示例
媒体I/O管理

设置视频摄像头

函数原型 int SetCamera (int device);
参数 device:整型,设备标识符。 注:-1为默认设备
返回值 整型,操作是否成功。0=成功,其它=参见附录2。
说明 设置当前视频通话所使用的摄像头。
示例 int ret = -1; UpdateData(true); ret = FreePPSDK::SetCamera(m_nCameraID); if (ret !=0) { AfxMessageBox(_T("设置摄像头失败")); return; }

设置声音输出设备

函数原型 int SetAudioOutput (int device);
参数 device:整型,扬声器设备标识符
返回值 整型,操作是否成功。0=成功,其它=参见附录2。
说明 设置声音输出设备 注:该功能未实现,采用默认设备输出。
示例

设置视频显示窗口

函数原型 int SetVideoDisplay(void *displayRemote,void *displayPreview);
参数 displayRemote:指针类型,用于显示远端视频(对方的图像)的窗口对象。(注:对象类型需根据操作系统进行选择)。 displayPreview:指针类型,用于显示近端视频(自己的图像)的窗口对象(自己的图像)。
返回值 整型,操作是否成功。0=成功,其它=参见附录2。
说明 设置视频通话中用于显示视频的窗口对象。 注:此接口需要在发起视频呼叫(MakeCall 或JoinConference)前或者收到视频来电请求接听后(AnswerCall之前)设置。
示例 int ret = -1; ret=FreePPSDK::SetVideoDisplay(GetDlgItem(IDC_STATIC_REMOTE_VIDEO)->GetSafeHwnd(), GetDlgItem(IDC_STATIC_LOCAL_VIDEO)->GetSafeHwnd()); if(ret < 0) { AfxMessageBox(_T("设置视频显示窗口失败")); }

开始视频发送

函数原型 int StartVideoSend ();
参数
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 手动开启本地视频的发送功能。 注:APP需通过SetParameter接口将"auto_send_video "参数设置为”0”时,此接口才有效。自动发送视频的模式包括: 0=手动,1=自动。SDK默认值为“1”,即视频通话接听后,自动发送本地视频。
示例 int ret = -1; UpdateData(true); ret = FreePPSDK::SetCamera(m_nCameraID); if (ret < 0) { AfxMessageBox(_T("设置摄像头失败")); return; } ret = FreePPSDK::StartVideoSend(); if (ret < 0) { AfxMessageBox(_T("开启视频发送失败")); return; }

停止视频发送

函数原型 int StopVideoSend ();
参数
返回值 整型,操作是否成功。0=成功,其它=参见附录2.
说明 停止本地视频发送。
示例 int ret = -1; ret = FreePPSDK::StopVideoSend(); if (ret < 0) { AfxMessageBox(_T("停止视频发送失败")); return; }

设置通话请求的回铃音

函数原型 int SetRingbackTone(char *ringbackFilePath);
参数 ringbackFilePath:字符串,App层Bundle或本地文件系统中回铃音文件的存储路径。
返回值 整型,操作是否成功。0=成功,其它=参见附录2。
说明 设置电话呼叫的回铃音。格式为pcm 16K 注:该功能暂未实现,默认路径为数据库路径,文件名为ringbacktone.pcm。
示例

设置网络摄像头

函数原型 int SetNetworkCamera(char *devURL, char* user, char* pass);
参数 devURL:字符串,网络摄像头的URL地址,即通过此URL地址SDK可以获得摄像头的有关服务信息,并自动连接摄像头的流媒体服务。 user:字符串(可选参数),访问网络摄像头的账号。 pass:字符串(可选参数),访问网络摄像头的密码。 resolution:整型,期望的视频分辨率。SDK将根据设备的实际能力,自动匹配与此参数最接近的视频分辨率。(参见附录4) quality:整型,期望的视频质量。SDK将根据设备的实际能力,自动匹配与此参数最接近的质量等级。(参见附录4)
返回值 整型,操作是否成功。0=成功,其它=参见附录2。
说明 设置SDK所使用的网络摄像头。一旦设置成功,则SDK将把网络摄像头的视频流作为本机采集的视频流发送给通话对端。 注:APP调用此函数时,SDK将自动连接指定的网络摄像头,以验证设备URL地址的有效性,但不会发送视频流。APP需通过调用StartVideoSend/StopVideoSend来控制视频流的发送。
示例

配置网络摄像头参数

函数原型 int ConfigNetworkCamera(int width, int height, int framerate, int quality);
参数 width/height:整型,期望的视频分辨率(图像宽度和高度)。SDK将根据设备的实际能力,自动匹配与此参数最接近的视频分辨率。 framerate:整型,期望的视频帧速率。SDK将根据设备的实际能力,自动匹配与此参数最接近的视频帧速率。 quality:整型,期望的视频质量。取值范围为0-2,0为最低,2为最高。
返回值 整型,操作是否成功。0=成功,其它=参见附录2。
说明 设置网络摄像头的工作参数。 注:若APP未设定网络摄像头的参数,则SDK默认按照352×288,25帧/s和中等质量水平工作。
示例

对讲功能接口

对讲功能接口的函数原型声明参见“FreePPSDKPTT_C.h”文件,主要提供进入或退出对讲频道、请求和释放发言权等控制功能。

频道/发言控制

进入语音对讲频道

函数原型 int EnterPTTRoom(char * roomID)
参数 roomID: 语音对讲频道的通信号码。
返回值 整型,操作是否成功。0=成功,其它=错误代码。
说明 进入预先分配的语音对讲频道,并自动处于收听语音状态。 注:此接口为异步接口,可触发回调函数onPTTStateEvent。APP可通过PTT状态通知得到是否已进入频道,以及对讲频道的当前状态。 注:语音对讲频道的通信号码需要预先申请。
示例 char dstAccounts[256] = { 0 }; int ret = -1; // 转换字符编码格式 CopyString(m_szCallee, dstAccounts, 256); // dstAccount中为频道的通信号码 ret = FreePPSDK::EnterPTTRoom(dstAccounts); If (! ret) { AfxMessageBox(_T("进入频道失败")); }

退出语音对讲频道

函数原型 int LeavePTTRoom(char * roomID)
参数 roomID: 语音对讲频道的通信号码。
返回值 整型,操作是否成功。0=成功,其它=错误代码。
说明 退出一个已进入的语音对讲频道。
示例 char dstAccounts[256] = { 0 }; int ret = -1; // 转换字符编码格式 CopyString(m_szCallee, dstAccounts, 256); ret =FreePPSDK::LeavePTTRoom(dstAccounts);

请求发言

函数原型 int PushTalk(char * roomID)
参数 roomID: 语音对讲频道的通信号码。
返回值 整型,操作是否成功。0=成功,其它=错误代码。
说明 请求指定语音对讲频道的发言权,并等待发言。 注:此接口为异步接口,可触发回调函数onPTTStateEvent。APP可通过PTT状态通知得到是否已获得发言权。
示例 if (pMsg->message == WM_LBUTTONDOWN) { if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_Push)->m_hWnd) FreePPSDK::PushTalk(dstAccounts); } else if (pMsg->message == WM_LBUTTONUP) { if (pMsg->hwnd == GetDlgItem(IDC_BUTTON_Push)->m_hWnd) FreePPSDK::ReleaseTalk(dstAccounts); }

释放发言权

函数原型 int ReleaseTalk(char * roomID)
参数 roomID: 语音对讲频道的FREEPP号码。
返回值 整型,操作是否成功。0=成功,其它=错误代码。
说明 释放指定频道的发言权,或取消发言请求
示例 参见PushTalk接口
频道状态通知
函数原型 void onPTTStateEvent(char * roomID, int state, char * speaker, int position)=0;
参数 roomID: 语音对讲频道的通信号码。 state: 语音对讲频道的当前状态。取值如下: PTT_STATE_IDLE(当前频道空闲,没有发言者) PTT_STATE_GRANTED(本机用户获得发言权,并进入发言状态) PTT_STATE_RELEASED(本机用户释放发言权,并恢复收听状态) PTT_STATE_QUEUED (本机用户正在排队等待发言权) PTT_STATE_DENY(服务器拒绝本机用户的发言请求) PTT_STATE_TAKEN(频道已被占用,其它用户正在发言) PTT_STATE_ENTER(已进入语音对讲频道) Speaker:当state为PTT_STATE_TAKEN时,指当前发言者的通信号码。 Position: 当state为PTT_STATE_QUEUE时,指在本机用户前面排队的其它发言者的个数。
返回值
说明 通知APP语音对讲频道的当前状态( PTT状态机)及频道的使用情况。 注:此接口为回调函数接口,APP应在传递给SDK的FreePPSDKDelegate对象类中实现此函数。 注:APP不能在此回调接口中执行长时任务,以免阻塞SDK的回调任务。
示例 //接口实现示例代码 void FreePPSDKDelegate::onPTTStateEvent(char * roomID, int state, char * speaker, int position) { switch(state) { case PTT_STATE_IDLE: break; } }

工作流程

启动流程

APP程序在启动时,应尽早完成SDK的初始化和AppKey认证工作。SDK运行时会产生用户数据库用于保存用户的相关信息,方便用户再次使用,在开始SDK初始化前需要设置数据库保存路径。启动流程如下图所示:

上图中,APP和SDK的具体交互流程如下:

一对一消息流程

上图中,APP和SDK的具体交互流程如下:

群组消息流程

上图中,APP和SDK的具体交互流程如下:

基本通话流程

上图中,APP和SDK的具体交互流程如下:

拒接电话流程

上图中,APP和SDK的具体交互流程如下:

呼叫保留/恢复流程

上图中,APP和SDK的具体交互流程如下(以主叫端为例):

基本会议流程

上图中,APP和SDK的具体交互流程如下:

会议拒接流程

上图中,APP和SDK的具体交互流程如下:

会议控制流程

上图中,所有与会者都进入会议后,APP和SDK的具体交互流程如下:

视频控制流程

上图为视频会议订阅流程,所有与会者都进入会议后,APP和SDK的具体交互流程如下:

语音对讲流程

上图中,APP和SDK的具体交互流程如下:

开发环境配置

4.5.1 Windows

Visual Studio 2013或以上版本。

4.5.2 Linux